/****************************************************************************
 *
 * Copyright (C) 2003-2008 Los Alamos National Security, LLC
 *                         Packet Analytics Corporation
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License Version 2 as
 * published by the Free Software Foundation.  You may not use, modify or
 * distribute this program under any other version of the GNU General
 * Public License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 ****************************************************************************/
package nfse.web;

/******
 * This API sits on top the socket-based API for query submission and
 * adds additional functionality not provided via sockets. 
 * 
 * This code is in active development and is not reliable in its current form.
 */

import java.io.*;
import java.util.*;

import javax.servlet.*;
import javax.servlet.http.*;

import nfse.*;
import nfse.gui.server.*;
import nfse.gui.query.*;

import java.net.*;
import java.sql.*;

import javax.net.*;

public class WebServiceAPI extends HttpServlet {

    /***************************************************************************
     * The JDBC connection to the metadata database (see metadata_psql.sql). The
     * createMetadaataStatement will connect to the database the first time it
     * is called.
     */
    private static Connection connectionMetadata = null;

    /***************************************************************************
     * The JDBC connection to the results database (see results_psql.sql). The
     * createMetadaataStatement will connect to the database the first time it
     * is called.
     */
    private static Connection connectionResult = null;

    /***************************************************************************
     * Defines output mode for comma separated values (csv).
     */
    final int CSV = 2;

    /***************************************************************************
     * Parts of the API are simply wrappers around code already implemented for
     * the web interface. This attribute is used to access the methods of that
     * implementation.
     */
    final QueryServiceImpl qsi = new QueryServiceImpl();

    /***************************************************************************
     * Defines output mode for raw logs.
     */
    final int RAW = 1;

    /***************************************************************************
     * Defines output mode for XML-encoded data. Data type implementations must
     * override the NetFSERecord toXML() method to enable this function.
     */
    final int XML = 3;

    /***************************************************************************
     * Creates a JDBC Statement providing access to the metadata database.
     * 
     * @return A JDBC Statement allowing access to the metadata database
     * @throws Exception
     *             Thrown when database is down or authentication parameters are
     *             incorrect
     */
    private Statement createMetadataStatement() throws Exception {
        Statement s = null;
        try {
            s = connectionMetadata.createStatement();
        } catch (Exception e) {
            Class.forName("org.postgresql.Driver");
            String url = "jdbc:postgresql://" + NetFSE.METADATA_HOST + "/" + NetFSE.METADATA_DATABASE;
            Properties props = new Properties();
            props.setProperty("user", NetFSE.METADATA_USER);
            props.setProperty("password", NetFSE.METADATA_PASSWORD);
            props.setProperty("client_encoding", "UTF8");

            connectionMetadata = DriverManager.getConnection(url, props);

            s = connectionMetadata.createStatement();
        }
        return s;
    }

    /***************************************************************************
     * Creates a JDBC Statement providing access to the results database.
     * 
     * @return A JDBC Statement allowing access to the results database
     * @throws Exception
     *             Thrown when database is down or authentication parameters are
     *             incorrect
     */
    private Statement createResultStatement() throws Exception {
        Statement s = null;
        try {
            s = connectionResult.createStatement();
        } catch (Exception e) {
            // If the connection has not been initialized or has died, try to
            // reconnect and create a statement. Still may fail if the server is
            // down, in which case a null will be returned.
            Class.forName("org.postgresql.Driver");
            String url = "jdbc:postgresql://localhost/" + NetFSE.RESULT_DB_DATABASE;
            Properties props = new Properties();
            props.setProperty("user", NetFSE.RESULT_DB_USER);
            props.setProperty("password", NetFSE.RESULT_DB_PASSWORD);
            props.setProperty("client_encoding", "UTF8");

            connectionResult = DriverManager.getConnection(url, props);

            s = connectionResult.createStatement();
        }
        return s;
    }

    private void delete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        PrintWriter out = null;
        String sql = "";
        try {
            out = new PrintWriter(response.getOutputStream());
            String queryID = request.getParameter("queryid");
            if ((queryID == null) || (queryID.length() == 0)) {
                out
                        .println("<NetFSE><QueryResult><Error message=\"Parameter 'queryid' was null or zero length.\"/></QueryResult></NetFSE>");
                out.close();
                return;
            }

            String deleteTypeStr = request.getParameter("deletetype");
            if ((deleteTypeStr == null) || (deleteTypeStr.length() == 0)) {
                out
                        .println("<NetFSE><QueryResult><Error message=\"Parameter 'deletetype' was null or zero length.\"/></QueryResult></NetFSE>");
                out.close();
                return;
            }

            String deleteSQL = request.getParameter("delete");
            if ((deleteSQL == null) || (deleteSQL.length() == 0)) {
                out
                        .println("<NetFSE><QueryResult><Error message=\"Parameter 'delete' was null or zero length.\"/></QueryResult></NetFSE>");
                out.close();
                return;
            }

            int deleteType = Integer.parseInt(deleteTypeStr);

            String user = request.getRemoteUser();

            StringBuffer temp = new StringBuffer();
            temp.append("<QueryResult ");

            Statement s1 = createResultStatement();

            sql = "select * from Queries where User_ID='" + user + "' and Query_ID='" + queryID + "'";
            ResultSet rs1 = s1.executeQuery(sql);
            if (!rs1.next()) {
                rs1.close();
                s1.close();
                throw (new Exception("User was not owner of query. Must be owner to execute 'delete' functoin."));
            }
            rs1.close();

            int[] types = NetFSE.getTypes();
            if (deleteType != 0) {
                types = new int[1];
                types[0] = deleteType;
            }
            int count = 0;
            for (int i = 0; i < types.length; i++) {
                sql = "select count(*) as a from " + queryID + "_" + types[i] + " where " + deleteSQL;
                rs1 = s1.executeQuery(sql);
                rs1.next();
                count += rs1.getInt("a");
                rs1.close();

                sql = "delete from " + queryID + "_" + types[i] + " where " + deleteSQL;
                s1.execute(sql);
            }

            temp.append(" count=\"" + count + "\" status=\"-1\">Deleted " + count + " matching records.</QueryResult>");

            sql = "select * from Queries where Query_ID='" + queryID + "'";
            rs1 = s1.executeQuery(sql);
            rs1.next();
            int status = rs1.getInt("Status");
            rs1.close();
            if (status == 1) {
                // Need to update counts
                for (int i = 0; i < types.length; i++) {
                    sql = "select count(*) as a from " + queryID + "_" + types[i];
                    rs1 = s1.executeQuery(sql);
                    rs1.next();
                    count = rs1.getInt("a");
                    rs1.close();

                    sql = "update Query_Types set Count=" + count + " where Query_ID='" + queryID + "' and Type_ID="
                            + types[i];
                    s1.execute(sql);
                }
            }

            s1.close();

            out.println("<NetFSE>");
            out.println(temp.toString());
            out.println("</NetFSE>");
            out.close();
        } catch (Exception E) {
            out.println("<NetFSE><QueryResult>");
            out.println("<Error message=\"" + E.getMessage() + "\">");
            E.printStackTrace(out);
            out.println("</Error>");
            out.println("</QueryResult></NetFSE>");
            out.close();
        }
    }

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/xml");
        String action = request.getParameter("action");
        if (action.equals("query")) {
            query(request, response);
        } else if (action.equals("searchstatus")) {
            searchStatus(request, response);
        } else if (action.equals("settimeout")) {
            settimeout(request, response);
        } else if (action.equals("remove")) {
            remove(request, response);
        } else if (action.equals("delete")) {
            delete(request, response);
        } else if (action.equals("get")) {
            get(request, response);
        } else if (action.equals("results")) {
            results(request, response);
        } else if (action.equals("history")) {
            history(request, response);
        }
    }

    private void get(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        PrintWriter out = null;
        String sql = "";
        try {
            out = new PrintWriter(response.getOutputStream());
            String nStr = request.getParameter("n");
            if ((nStr == null) || (nStr.length() == 0)) {
                throw (new Exception("Parameter 'n' was null or zero length."));

            }
            String offsetStr = request.getParameter("offset");
            if ((offsetStr == null) || (offsetStr.length() == 0)) {
                throw (new Exception("Parameter 'offset' was null or zero length."));

            }
            String typeStr = request.getParameter("type");
            if (typeStr == null) {
                throw (new Exception("Parameter 'type' was null or zero length."));

            }
            String queryID = request.getParameter("queryid");
            if ((queryID == null) || (queryID.length() == 0)) {
                throw (new Exception("Parameter 'queryid' was null or zero length."));

            }
            String where = request.getParameter("where");
            if (where == null)
                where = "";
            String orderby = request.getParameter("orderby");
            if (orderby == null)
                orderby = "";
            int type = Integer.parseInt(typeStr);
            int n = Integer.parseInt(nStr);
            int offset = Integer.parseInt(offsetStr);
            String table = queryID + "_" + type;

            Statement s1 = createResultStatement();

            sql = "select * from Queries where Query_ID=\'" + queryID + "\'";
            ResultSet rs1 = s1.executeQuery(sql);
            if (rs1.next()) {

                Statement s2 = createResultStatement();
                Timestamp now = new Timestamp(System.currentTimeMillis());
                sql = "select * from Queries where Query_ID='" + queryID + "' and ts is not null";
                ResultSet rs2 = s2.executeQuery(sql);
                if (rs2.next()) {
                    rs2.close();
                    sql = "update Queries set TS='" + now + "' where Query_ID='" + queryID + "'";
                    s2.execute(sql);
                }
                s2.close();

                int status = rs1.getInt("Status");
                int count = 0;
                if (where.length() == 0) {
                    if (status == 1) {
                        rs1.close();
                        sql = "select * from Query_Types where Query_ID='" + queryID + "' and Type_ID=" + type;
                        rs1 = s1.executeQuery(sql);
                        rs1.next();
                        count = rs1.getInt("Count");
                    } else if (status == 0) {
                        rs1.close();
                        sql = "select count(*) as a from " + table + "";
                        rs1 = s1.executeQuery(sql);
                        rs1.next();
                        count = rs1.getInt("a");
                    }
                } else {
                    int idx = where.toUpperCase().indexOf("WHERE");
                    if (idx >= 0)
                        where = where.substring(idx + 6);
                    sql = "select count(*) as a from " + queryID + ", " + table + " where Type_ID=" + type + " and "
                            + queryID + ".ID=" + queryID + "_" + type + ".ID ";
                    if (where.length() > 0) {
                        sql += " and " + where;
                    }
                    rs1 = s1.executeQuery(sql);
                    rs1.next();
                    count = rs1.getInt("a");

                }
                rs1.close();

                if (offset < 0)
                    offset = 0;

                int first = offset + 1;
                int last = offset + n;
                if (last > count)
                    last = count;

                String record = "";
                String line = "";

                int sensor = -1;

                sql = "select * from " + queryID + ", " + table + " where Type_ID=" + type + " and " + queryID + ".ID="
                        + queryID + "_" + type + ".ID ";
                if (where.length() > 0) {
                    sql += " and " + where;
                }
                if (orderby.length() > 0) {
                    sql += " order by " + orderby;
                }
                sql += " limit " + n + " offset " + offset;

                rs1 = s1.executeQuery(sql);

                out.println("<NetFSE>");
                out.print("<QueryResult ");

                out.println("queryid=\"" + queryID + "\" status=\"" + status + "\" count=\"" + count + "\" first=\""
                        + first + "\" last=\"" + last + "\">");

                // out.println("<SQL>" + NetFSEUtil.xmlify(sql) + "</SQL>");

                NetFSERecord rec = NetFSE.getTypeClass(type);

                while (rs1.next()) {
                    record = rs1.getString("Record");
                    sensor = rs1.getInt("Sensor_ID");
                    line = NetFSEUtil.convertFromHex(record);
                    System.out.println(sensor + ": " + line);
                    NetFSERecord temp = rec.generate(line, sensor);

                    out.println(temp.toXML());

                }
                rs1.close();

            } else {
                rs1.close();
                throw (new Exception("Invalid query specified in 'queryid' parameter."));
            }

            s1.close();

            out.println("</QueryResult></NetFSE>");
            out.close();
        } catch (Exception E) {
            out.println("<NetFSE><QueryResult>");
            // out.println("<SQL>" + sql + "</SQL>");
            out.println("<Error message=\"" + E.getMessage() + "\">");
            E.printStackTrace(out);
            out.println("</Error>");
            out.println("</QueryResult></NetFSE>");
            out.close();
        }
    }

    private void history(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        PrintWriter out = null;
        try {
            out = response.getWriter();

            out.println("<NetFSE><SearchHistory>");

            QueryOptions[] options = qsi.queryHistory();
            for (int i = 0; i < options.length; i++) {
                out.println(options[i].toXML());
            }

            out.println("</SearchHistory></NetFSE>");
            out.close();
        } catch (Exception E) {
            out.println("<NetFSE><QueryResult>");
            out.println("<Error message=\"" + E.getMessage() + "\">");
            E.printStackTrace(out);
            out.println("</Error>");
            out.println("</QueryResult></NetFSE>");
            out.close();
        }
    }

    private boolean isOwner(HttpServletRequest request, String queryID) {
        try {
            Statement statement = createMetadataStatement();
            boolean owner = false;
            String userName = request.getRemoteUser();

            ResultSet rs = statement.executeQuery("select * from Users where User_Name='" + userName + "'");
            if (rs.next()) {
                if (rs.getInt("Admin") != 0) {
                    rs.close();
                    statement.close();
                    return true;
                }
            }
            rs.close();

            rs = statement.executeQuery("select * from Queries where Query_ID='" + queryID + "' and User_ID='"
                    + userName + "'");
            if (rs.next())
                owner = true;
            rs.close();

            statement.close();
            return owner;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    private void query(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        Socket s = null;
        Socket s2 = null;
        PrintWriter out = null;
        try {
            out = response.getWriter();
            
            String note = request.getParameter("note");
            if (note == null)
                note = "";
            note = note.replaceAll("'", " ");
            note = note.replaceAll("\"", " ");

            String resultType = request.getParameter("results");
            if (resultType == null || resultType.length() == 0)
                resultType = "db";

            String queryBase = request.getParameter("query");
            String queryHead = queryBase.substring(0, queryBase.indexOf(">") + 1);
            String queryBody = queryBase.substring(queryBase.indexOf(">") + 1);
            // query = queryHead;
            String typesStr = request.getParameter("types");

            String[] tempTypes = null;
            if (typesStr == null || typesStr.length() == 0) {
                int[] types = NetFSE.getTypes();
                tempTypes = new String[types.length];
                for (int i = 0; i < tempTypes.length; i++)
                    tempTypes[i] = "" + types[i];
            } else {
                tempTypes = typesStr.split(" ");
            }
            Vector<String> tempQueries = new Vector<String>();
            Vector<Integer> tempTypes2 = new Vector<Integer>();
            for (int i = 0; i < tempTypes.length; i++) {
                try {
                    tempTypes2.addElement(new Integer(tempTypes[i].trim()));
                    String query = queryHead + "<Data type=\"" + Integer.parseInt(tempTypes[i].trim()) + "\"/>"
                            + queryBody;
                    tempQueries.addElement(query);
                } catch (Exception E) {
                    // no op
                }
            }
            
            String[] queries = new String[tempQueries.size()];
            for (int i = 0; i < queries.length; i++)
                queries[i] = (String) tempQueries.elementAt(i);

            int[] types = new int[tempTypes2.size()];
            for (int i = 0; i < tempTypes2.size(); i++) {
                types[i] = ((Integer) tempTypes2.elementAt(i)).intValue();
            }

            int limit = -1;
            try {
                limit = Integer.parseInt(request.getParameter("limit"));
            } catch (Exception e) {
                // e.printStackTrace(out);
            }
            int total = -1;
            try {
                total = Integer.parseInt(request.getParameter("total"));
            } catch (Exception e) {
                // e.printStackTrace(out);
            }

            if (resultType.equals("db")) {
                // This result set should be stored in the results database.
                // Processing is done asynchronously so make a call to
                // QueryServiceImpl.query and return
                // QueryServiceImpl qsi = new QueryServiceImpl();
                String queryID = qsi.query(queryBase, note, types, limit, total);

                if (!queryID.equals("failed")) {
                    out.println("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>");
                    out.print("<NetFSE");
                    out.println("><QueryResult id=\"" + queryID + "\">");

                    out.println("Query is being generated with queryid of " + queryID + "</QueryResult></NetFSE>");

                    out.flush();
                    out.close();

                } else {
                    out.println("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>");
                    out.print("<NetFSE");
                    out.println("><QueryResult id=\"" + queryID + "\">");

                    out.println("The query failed.</QueryResult></NetFSE>");

                    out.flush();
                    out.close();
                }
                return;
            } else if (resultType.equals("stream")) {
                int format = XML;
                String formatStr = request.getParameter("format");
                if (formatStr == null || formatStr.length() == 0)
                    format = XML;
                else if (formatStr.equals("raw")) {
                    format = RAW;
                    response.setContentType("application/base64");
                } else if (formatStr.equals("csv")) {
                    format = CSV;
                    response.setContentType("application/base64");
                }

                out.println("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>");
                out.print("<NetFSE><QueryResult>");

                String result = queryToStream(queries, total, limit, out, format);
                if (result != null && result.length() > 0) {
                    out.println(result);
                }
                out.println("</QueryResult></NetFSE>");
                out.flush();
                out.close();
            } else {
                out.println("<NetFSE><QueryResult>");
                out.println("<Error message=\"Invalid result type specified.\">");
                out.println("</Error>");
                out.println("</QueryResult></NetFSE>");
                out.flush();
                out.close();
            }

        } catch (Exception E) {
            out.println("<NetFSE><QueryResult>");
            out.println("<Error message=\"" + E.getMessage() + "\">");
            E.printStackTrace(out);
            out.println("</Error>");
            out.println("</QueryResult></NetFSE>");
            out.close();

            try {
                if (s != null)
                    s.close();
            } catch (IOException ioe) {
                ioe.printStackTrace(out);
            }
            try {
                if (s2 != null)
                    s2.close();
            } catch (IOException ioe2) {
                ioe2.printStackTrace(out);
            }
        }
    }

    private String queryToStream(String[] queries, long total, long limit, PrintWriter out, int mode) {
        Socket socket = null;
        Socket socket2 = null;
        DataInputStream resultIn = null;
        try {
            String insertSQL = "";
            for (int x = 0; x < queries.length; x++) {
                // SocketFactory sf = SSLSocketFactory.getDefault();
                SocketFactory sf = SocketFactory.getDefault();
                socket = sf.createSocket(NetFSE.QUERY_HOST, NetFSE.QUERY_SERVER_PORT);
                PrintWriter socketOut = new PrintWriter(socket.getOutputStream());
                DataInputStream socketIn = new DataInputStream(socket.getInputStream());

                ServerSocketFactory ssf = ServerSocketFactory.getDefault();
                ServerSocket ss = ssf.createServerSocket();
                try {

                    if ((queries[x].indexOf(" user=\"") > 0) && (queries[x].indexOf(" password=\"") > 0)) {
                        // no op
                    }

                    System.out.println(queries[x]);

                    int endIdx = queries[x].lastIndexOf("</Query>");
                    if (endIdx >= 0) {
                        queries[x] = queries[x].substring(0, endIdx);
                    } else {
                        endIdx = queries[x].lastIndexOf("/>");
                        queries[x] = queries[x].substring(0, endIdx) + ">";
                    }

                    ss.bind(null);

                    queries[x] += "<SocketResult host=\"" + NetFSE.TOMCAT_HOST + "\" port=\"" + ss.getLocalPort()
                            + "\"/>";

                    queries[x] += "</Query>";

                    System.out.println(queries[x]);

                    socketOut.println(queries[x]);
                    socketOut.println("<--DiSARM: end query-->");
                    socketOut.flush();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                // out.println(queries[x] + "<br>");

                int reply = socketIn.readInt();
                if (reply >= 0)
                    socket2 = ss.accept();

                if (reply < 0) {

                    return "Query failed";
                } else {

                    resultIn = new DataInputStream(socket2.getInputStream());
                    int count = 0;
                    
                    int type = -1;
                    int sensor = -1;
                    int len = -1;
                    byte[] bytes = null;
                    int bytesRead;
                    String line = null;
                    try {
                        type = resultIn.readInt();
                        if (type == -100) {
                            line = null;
                        } else {
                            sensor = resultIn.readInt();
                            len = resultIn.readInt();
                            bytes = new byte[len];
                            bytesRead = 0;
                            while (bytesRead < len)
                                bytesRead += resultIn.read(bytes, bytesRead, len - bytesRead);
                            // for (int j = 0; j < len; j++)
                            // bytes[j] = (byte) resultIn.read();

                            line = new String(bytes);
                        }
                    } catch (Exception E) {
                        line = null;
                    }
                    insertSQL = "";
                    NetFSERecord rec = NetFSE.getTypeClass(type);
                    NetFSERecord temp = null;
                    int typeCount = 0;

                    if (mode == CSV) {
                        out.println(rec.getCSVColNames());
                    }

                    while (line != null) {

                        if ((total != -1) && (count == total)) {
                            line = null;
                            break;
                        }

                        if ((limit == -1) || (typeCount < limit)) {
                            try {
                                count++;
                                temp = rec.generate(line, sensor);
                                if (temp != null) {
                                    if (mode == XML)
                                        out.println(temp.toXML());
                                    else if (mode == RAW)
                                        out.println(new String(bytes));
                                    else
                                        out.println(temp.toCSV());
                                    typeCount++;
                                } else
                                    count--;
                            } catch (Exception e) {
                                System.out.println(insertSQL);
                                e.printStackTrace();
                                count--;
                                typeCount--;
                            }
                        } else {
                            line = null;
                        }

                        if (line != null) {
                            try {
                                type = resultIn.readInt();
                                if (type == -100) {
                                    line = null;
                                } else {
                                    sensor = resultIn.readInt();
                                    len = resultIn.readInt();
                                    bytes = new byte[len];
                                    bytesRead = 0;
                                    while (bytesRead < len)
                                        bytesRead += resultIn.read(bytes, bytesRead, len - bytesRead);
                                    line = new String(bytes);
                                }
                            } catch (Exception E) {
                                E.printStackTrace();
                                line = null;
                            }
                        }

                    } // End main while loop
                }

                if (resultIn != null) {
                    resultIn.close();
                }
                socketOut.close();
                socketIn.close();
                if (socket2 != null)
                    socket2.close();
                socket.close();
                ss.close();
            }

        } catch (Exception E) {
            out.println("<NetFSE><QueryResult>");
            out.println("<Error message=\"" + E.getMessage() + "\">");
            E.printStackTrace(out);
            out.println("</Error>");
            out.println("</QueryResult></NetFSE>");
            out.close();
        }
        return "";
    }

    private void remove(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        PrintWriter out = null;
        try {
            out = new PrintWriter(response.getOutputStream());
            String queryID = request.getParameter("queryid");
            if ((queryID == null) || (queryID.length() == 0)) {
                throw (new Exception("Parameter 'queryid' was null or zero length."));
            }

            String user = request.getRemoteUser();

            boolean owner = isOwner(request, queryID);

            if (!owner)
                throw (new Exception("User was not owner of query. Must be owner to execute 'remove' function."));

            StringBuffer temp = new StringBuffer();
            temp.append("<QueryResult ");

            Statement s1 = createResultStatement();
            Statement s2 = createResultStatement();
            ResultSet rs1 = s1.executeQuery("select * from Queries where User_ID='" + user + "' and Query_ID=\""
                    + queryID + "\" ");
            // ResultSet rs1 = s1.executeQuery("select * from Queries ");
            if (rs1.next()) {
                queryID = rs1.getString("Query_ID");
                try {
                    int[] types = NetFSE.getTypes();
                    for (int i = 0; i < types.length; i++) {
                        try {
                            s2.execute("drop table " + queryID + "_" + types[i]);
                        } catch (Exception E) {
                        }
                    }
                    s2.execute("drop table " + queryID);

                    s2.execute("delete from Queries where Query_ID=\"" + queryID + "\"");
                    s2.execute("delete from Query_Types where Query_ID=\"" + queryID + "\"");
                } catch (Exception e) {

                }
            }
            temp.append(" status=\"-1\">Query removed successfully.</QueryResult>");
            rs1.close();
            s1.close();
            s2.close();

            out.println("<NetFSE>");
            out.println(temp.toString());
            out.println("</NetFSE>");
            out.close();
        } catch (Exception E) {
            out.println("<NetFSE><QueryResult>");
            out.println("<Error message=\"" + E.getMessage() + "\">");
            E.printStackTrace(out);
            out.println("</Error>");
            out.println("</QueryResult></NetFSE>");
            out.close();
        }
    }

    private void results(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        PrintWriter out = null;
        try {
            out = response.getWriter();

            StringBuffer temp = new StringBuffer();

            QuerySummary[] summaries = qsi.myQueries();
            for (int i = 0; i < summaries.length; i++) {
                temp.append(summaries[i].toXML());
            }

            out.println("<NetFSE><SearchResults>");
            out.println(temp.toString());
            out.println("</SearchResults></NetFSE>");
            out.close();
        } catch (Exception E) {
            out.println("<NetFSE><QueryResult>");
            out.println("<Error message=\"" + E.getMessage() + "\">");
            E.printStackTrace(out);
            out.println("</Error>");
            out.println("</QueryResult></NetFSE>");
            out.close();
        }
    }

    private void searchStatus(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        PrintWriter out = null;
        try {
            out = new PrintWriter(response.getOutputStream());
            String queryID = request.getParameter("queryid");
            if ((queryID == null) || (queryID.length() == 0)) {
                throw (new Exception("Parameter 'queryid' was null or zero length."));
            }

            String typeStr = request.getParameter("type");
            if (typeStr == null) {
                typeStr = "";
            }

            StringBuffer temp = new StringBuffer("<NetFSE>");

            Statement s1 = createResultStatement();
            ResultSet rs1 = s1.executeQuery("select * from Queries where Query_ID='" + queryID + "'");
            if (rs1.next()) {
                int status = rs1.getInt("Status");
                int count = rs1.getInt("Count");
                Timestamp ts = rs1.getTimestamp("TS");
                String note = rs1.getString("Note");

                temp.append("<SearchInfo status=\"" + status + "\" count=\"" + count + "\" timestamp=\"" + ts
                        + "\" note=\"" + NetFSEUtil.xmlify(note) + "\">");
                rs1.close();

                int[] types = NetFSE.getTypes();
                for (int i = 0; i < types.length; i++) {
                    String sql = "select count(*) as a, min(startts) as b, max(startts) as c from " + queryID + "_"
                            + types[i];
                    try {
                        rs1 = s1.executeQuery(sql);
                        rs1.next();
                        temp.append("<TypeInfo typeid=\"" + types[i] + "\" typename=\"" + NetFSE.getTypeName(types[i])
                                + "\" count=\"" + rs1.getInt("a") + "\" mints=\"" + rs1.getTimestamp("b")
                                + "\" maxts=\"" + rs1.getTimestamp("c") + "\"/>");
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                }

                temp.append("</SearchInfo>");

            } else {
                rs1.close();
                s1.close();
                throw (new Exception("The queryid specified was invalid."));
            }

            s1.close();

            temp.append("</NetFSE>");

            out.println(temp.toString());
            out.close();

        } catch (Exception E) {
            out.println("<NetFSE><QueryResult>");
            out.println("<Error message=\"" + E.getMessage() + "\">");
            E.printStackTrace(out);
            out.println("</Error>");
            out.println("</QueryResult></NetFSE>");
            out.close();
        }
    }

    private void settimeout(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        PrintWriter out = null;
        String sql = "";
        try {
            out = new PrintWriter(response.getOutputStream());
            String queryID = request.getParameter("queryid");
            if ((queryID == null) || (queryID.length() == 0)) {
                out.println("<NetFSE><QueryResult>Parameter 'queryid' was null or zero length.</QueryResult></NetFSE>");
                out.close();
                return;
            }

            Timestamp timeoutTS = null;
            String timeout = request.getParameter("timeout");
            if (timeout != null && timeout.length() > 0 && !timeout.equals("null")) {
                timeoutTS = Timestamp.valueOf(timeout);
            }

            StringBuffer temp = new StringBuffer();
            temp.append("<QueryResult ");

            Statement s1 = createResultStatement();

            sql = "update Queries set TS='" + timeout + "' where Query_ID='" + queryID + "'";
            s1.execute(sql);
            s1.close();

            String queryText = "";
            if (timeoutTS == null)
                queryText = "Query " + queryID + " set to never timeout.";
            else
                queryText = "Query " + queryID + " set to timeout after " + timeoutTS + ".";
            temp.append(" status=\"-1\">" + queryText + "</QueryResult>");

            out.println("<NetFSE>");
            out.println(temp.toString());
            out.println("</NetFSE>");
            out.close();
        } catch (Exception E) {
            out.println("<NetFSE><QueryResult>");
            out.println("<Error message=\"" + E.getMessage() + "\">");
            E.printStackTrace(out);
            out.println("</Error>");
            out.println("</QueryResult></NetFSE>");
            out.close();
        }
    }

}
